/*
 * @Author: tongbin.xtb
 * @Date: 2018-11-29 17:54:37
 * @Last Modified by: tongbin.xtb
 * @Last Modified time: 2018-12-03 21:10:30
 */

import { getPointAnchor, getControlPointsBySourceAndTarget,
  getBBoxAnchors, insertPoint, isVertical, bboxSideByLine, getVerticalPoint,
  oppositeAnchorIndex, middleInLine
} from './utils';

/**
 * 节点挪动时，重新计算点位置
 * @param {object} model 线模型
 * @param {object} source 起始节点
 * @param {object} target 结束节点
 * @return {object} 可能的辅助线
 */
export function handleNodeMove(model, source, target) {
  // 移动节点时造成的线段合并
  let helpLine;
  if (!model.nodeMoved) {
    return;
  }
  const sourceMoved = model.nodeMoved.item === source.id;
  const targetMoved = model.nodeMoved.item === target.id;
  const endBBox = sourceMoved ? source.getBBox() : target.getBBox();
  const delta = model.nodeMoved.delta;
  const startBBox = {
    minX: endBBox.minX - delta.x,
    maxX: endBBox.maxX - delta.x,
    centerX: endBBox.centerX - delta.x,
    minY: endBBox.minY - delta.y,
    maxY: endBBox.maxY - delta.y,
    centerY: endBBox.centerY + delta.y,
    height: endBBox.height,
    width: endBBox.width
  };
  const cp = model.controlPoints;
  if (cp.length === 2) {
    // 没有控制点
    // 重新计算临界点
    const { sourcePoint, targetPoint } = getControlPointsBySourceAndTarget(source, target);
    if (model.sourceJoint && sourcePoint.index === model.sourceJoint.index) {
      sourcePoint.point = getBBoxAnchors(source.getBBox())[sourcePoint.index];
      sourcePoint.point.x += model.sourceJoint.delta.x;
      sourcePoint.point.y += model.sourceJoint.delta.y;
    }
    if (model.targetJoint && targetPoint.index === model.targetJoint.index) {
      targetPoint.point = getBBoxAnchors(target.getBBox())[targetPoint.index];
      targetPoint.point.x += model.targetJoint.delta.x;
      targetPoint.point.y += model.targetJoint.delta.y;
    }
    const points = insertPoint(sourcePoint, targetPoint);
    model.controlPoints = points;
  } else {
    // 离移动节点最近的两个控制点形成的线不会变动
    // 离移动节点上的控制点距离为2的节点不会变动
    let baseIndex;
    if (sourceMoved) {
      baseIndex = 1;
    } else {
      baseIndex = cp.length - 3;
    }
    const lineVertical = isVertical(cp, baseIndex);
    // bbox在
    const startSide = bboxSideByLine(startBBox, cp, baseIndex);
    const endSide = bboxSideByLine(endBBox, cp, baseIndex);
    const memoedPoint = sourceMoved ? model.sourceJoint : model.targetJoint;
    if (startSide === endSide) {
      const anchorPoint = getBBoxAnchors(endBBox)[memoedPoint.index];
      // 因为移动而形成的
      const jointPoint = {
        x: anchorPoint.x + memoedPoint.delta.x,
        y: anchorPoint.y + memoedPoint.delta.y
      };
      const baseLinePoint = getVerticalPoint(jointPoint, cp, baseIndex);
      if (sourceMoved) {
        model.controlPoints.splice(0, 2, jointPoint, baseLinePoint);
      } else if (targetMoved) {
        model.controlPoints.splice(baseIndex + 1, 2, baseLinePoint, jointPoint);
      }
    } else {
      // 保持的记录已经没有意义
      if (endSide === 0) {
        if (cp.length === 3) {
          // 只有3个控制点，起始控制点被改变
          const { sourcePoint, targetPoint } = getControlPointsBySourceAndTarget(source, target);
          const points = insertPoint(sourcePoint, targetPoint);
          model.controlPoints = points;
        } else {
          // 从一边挪到了基线上
          // 分四种情况讨论，垂直，在基线上方，在基线下方；水平，在基线左边，在基线右边
          const midPoint = middleInLine(cp, baseIndex);
          let anchorIndex;
          if (lineVertical) {
            if (midPoint.y < endBBox.centerY) {
              anchorIndex = 0;
            } else {
              anchorIndex = 2;
            }
          } else if (midPoint.x < endBBox.centerX) {
            anchorIndex = 3;
          } else {
            anchorIndex = 1;
          }
          const anchorPoint = getBBoxAnchors(endBBox)[anchorIndex];
          if (sourceMoved) {
            const baseLinePoint = getVerticalPoint(anchorPoint, cp, baseIndex + 1);
            model.controlPoints.splice(0, 3, anchorPoint, baseLinePoint);
            model.sourceJoint = {
              index: anchorIndex,
              delta: {
                x: 0,
                y: 0
              }
            };
          } else if (targetMoved) {
            const baseLinePoint = getVerticalPoint(anchorPoint, cp, baseIndex - 1);
            model.controlPoints.splice(baseIndex, 3, baseLinePoint, anchorPoint);
            model.targetJoint = {
              index: anchorIndex,
              delta: {
                x: 0,
                y: 0
              }
            };
          }
        }
      } else {
        // 挪到了另一边
        const anchorIndex = oppositeAnchorIndex(memoedPoint.index);
        const anchorPoint = getBBoxAnchors(endBBox)[anchorIndex];
        const baseLinePoint = getVerticalPoint(anchorPoint, cp, baseIndex);
        if (sourceMoved) {
          model.controlPoints.splice(0, 2, anchorPoint, baseLinePoint);
          model.sourceJoint = {
            index: anchorIndex,
            delta: {
              x: 0,
              y: 0
            }
          };
        } else if (targetMoved) {
          model.controlPoints.splice(baseIndex + 1, 2, baseLinePoint, anchorPoint);
          model.targetJoint = {
            index: anchorIndex,
            delta: {
              x: 0,
              y: 0
            }
          };
        }
      }
    }

  }
  return helpLine;
}

export function saveJointMoved(model, source, target) {
  const cp = model.controlPoints;
  if (source) {
    const { point, index } = getPointAnchor(cp[0], source.getBBox());
    model.sourceJoint = {
      index,
      delta: {
        x: cp[0].x - point.x,
        y: cp[0].y - point.y
      }
    };
  }
  if (target) {
    const { point, index } = getPointAnchor(cp[cp.length - 1], target.getBBox());
    model.targetJoint = {
      index,
      delta: {
        x: cp[cp.length - 1].x - point.x,
        y: cp[cp.length - 1].y - point.y
      }
    };
  }
}
